﻿using Microsoft.Win32;
using Newtonsoft.Json;
using ReNameEx.Model;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using Wpf.Ui;
using Wpf.Ui.Appearance;
using Wpf.Ui.Controls;
using Wpf.Ui.Extensions;
using File = System.IO.File;

namespace ReNameEx
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : FluentWindow
    {
        private string _RulePath = Path.Combine(Environment.CurrentDirectory, "rules.json");
        public List<ReExRuleBase> Rules = new List<ReExRuleBase>();
        public List<ReExFile> Files = new List<ReExFile>();
        public SnackbarService _SnackbarService = new SnackbarService();

        public HashSet<string> DisplayList = new HashSet<string>()
        {
            "IsApply","FileName","NewFileName","DirPath"
        };

        public MainWindow()
        {
            InitializeComponent();
            ViewChange();
            _SnackbarService.SetSnackbarPresenter(SnackbarMessage);
            ApplicationThemeManager.Apply(ApplicationTheme.Dark);

            if (File.Exists(_RulePath))
            {
                var listDict = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(File.ReadAllText(_RulePath));
                if (listDict != null)
                {
                    foreach (var item in listDict)
                    {
                        string? typeName = item["TypeName"].ToString();
                        if (!string.IsNullOrEmpty(typeName))
                        {
                            Type? type = Type.GetType(typeName);
                            if (type != null && typeof(ReExRuleBase).IsAssignableFrom(type))
                            {
                                // 将字典重新序列化为 JSON 字符串，再反序列化为目标类型
                                string itemJson = JsonConvert.SerializeObject(item);
                                var addRule = JsonConvert.DeserializeObject(itemJson, type) as ReExRuleBase;
                                if (addRule != null)
                                    Rules.Add(addRule);
                            }

                        }
                    }
                }
            }
            Rules = Rules.OrderBy(x => x.Order).ToList();
            RuleList.ItemsSource = Rules;
            FileList.ItemsSource = Files.ToList();
        }

        private void SaveRules()
        {
            Rules = Rules.OrderBy(x => x.Order).ToList();
            RuleList.ItemsSource = Rules;
            File.WriteAllText(_RulePath, JsonConvert.SerializeObject(Rules));
            PrewRule();
        }


        private async Task ShowSampleDialogAsync()
        {
            // Defining dialog object
            ContentDialog myDialog = new()
            {
                Title = "My sample dialog",
                Content = "Content of the dialog",
                CloseButtonText = "Close button",
                PrimaryButtonText = "Primary button",
                SecondaryButtonText = "Secondary button",
            };

            // Setting the dialog container
            myDialog.DialogHost = ContentPresenterForDialogs;

            // Showing the dialog
            await myDialog.ShowAsync(CancellationToken.None);
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            var editRule = new EditRule();
            editRule.ShowDialog();
            if (editRule.Result != null)
            {
                if (editRule.Result.Order == 0)
                    editRule.Result.Order = Rules.Count;
                Rules.Add(editRule.Result);
                SaveRules();
            }
            // await Application.Current.Dispatcher.InvokeAsync(ShowSampleDialogAsync);
        }

        public void PrewRule()
        {
            foreach (var file in Files)
                file.NewFileName = file.FileName;

            foreach (var rule in Rules)
                rule.PrewRule(Files);

            FileList.ItemsSource = Files.ToList();
        }

        private void BtnAddFolder_Click(object sender, RoutedEventArgs e)
        {
            OpenFolderDialog folderDialog = new OpenFolderDialog();
            folderDialog.Multiselect = true;
            folderDialog.ShowDialog();
            var refiles = AddFolderFile(folderDialog.FolderNames);
            if (refiles.Count > 0)
                Files.AddRange(refiles);
            PrewRule();
        }


        private List<ReExFile> AddFolderFile(string[] folderNames)
        {
            List<ReExFile> refiles = new List<ReExFile>();
            if (folderNames.Length > 0)
            {
                foreach (string dir in folderNames)
                {
                    var directoryInfo = new DirectoryInfo(dir);
                    var sysList = directoryInfo.GetFileSystemInfos();
                    foreach (var fileSystem in sysList)
                    {
                        #region 过滤隐藏和系统文件
                        if ((fileSystem.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden && IsApplyHidden.IsChecked == false)
                            continue;

                        if ((fileSystem.Attributes & FileAttributes.System) == FileAttributes.System)
                            continue;

                        if ((fileSystem.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
                        {
                            if (IsApplyFolder.IsChecked == true)
                            {
                                refiles.Add(new ReExFile()
                                {
                                    FileName = fileSystem.Name,
                                    DirPath = dir,
                                    IsApply = true
                                });
                            }
                            if (IsApplySubFolderFile.IsChecked == true)
                                refiles.AddRange(AddFolderFile([fileSystem.FullName]));

                            continue;
                        }
                        #endregion

                        if ((IsApplyFolder.IsChecked == false || IsOnlyFolder.IsChecked == false) 
                            && !Files.Exists(x => x.FileName.Equals(fileSystem.Name)))
                        {
                            refiles.Add(new ReExFile()
                            {
                                FileName = fileSystem.Name,
                                DirPath = dir,
                                IsApply = true
                            });
                        }

                    }
                }
            }
            return refiles;
        }

        private void BtnAddFile_Click(object sender, RoutedEventArgs e)
        {
            var fileDialog = new OpenFileDialog();
            fileDialog.Multiselect = true;
            fileDialog.ShowDialog();
            if (fileDialog.FileNames.Length > 0)
            {
                List<ReExFile> refiles = new List<ReExFile>();
                foreach (string fileName in fileDialog.FileNames)
                {
                    FileInfo fileInfo = new FileInfo(fileName);
                    if (fileInfo.DirectoryName != null)
                    {
                        if (!Files.Exists(x => x.FileName.Equals(fileInfo.Name)))
                        {
                            refiles.Add(new ReExFile()
                            {
                                FileName = fileInfo.Name,
                                DirPath = fileInfo.DirectoryName ?? "",
                                IsApply = true
                            });
                        }
                    }
                }
                Files.AddRange(refiles);
                PrewRule();
            }
        }

        private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            SaveRules();
            PrewRule();
        }

        private void RemoveFile_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in FileList.SelectedItems)
            {
                var fileInfo = item as ReExFile;
                if (fileInfo != null)
                {
                    Files.RemoveAll(x => x.FilePath.Equals(fileInfo.FilePath));
                }
            }
            PrewRule();
        }

        private void RemoveRule_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in RuleList.SelectedItems)
            {
                var rule = item as ReExRuleBase;
                if (rule != null)
                    Rules.Remove(rule);
            }
            SaveRules();
            PrewRule();
        }

        private void UpRule_Click(object sender, RoutedEventArgs e)
        {
            if (RuleList.SelectedIndex > 0)
            {
                int aOrder = Rules[RuleList.SelectedIndex].Order;
                int bOrder = Rules[RuleList.SelectedIndex - 1].Order;
                Rules[RuleList.SelectedIndex].Order = bOrder;
                Rules[RuleList.SelectedIndex - 1].Order = aOrder;
            }
            SaveRules();
            PrewRule();
        }
        private void DownRule_Click(object sender, RoutedEventArgs e)
        {
            if (RuleList.SelectedIndex < Rules.Count - 1)
            {
                int aOrder = Rules[RuleList.SelectedIndex].Order;
                int bOrder = Rules[RuleList.SelectedIndex + 1].Order;
                Rules[RuleList.SelectedIndex].Order = bOrder;
                Rules[RuleList.SelectedIndex + 1].Order = aOrder;
            }
            SaveRules();
            PrewRule();
        }

        private async void ApplyRule_Click(object sender, RoutedEventArgs e)
        {
            var applyList = Files.Where(x => x.IsApply);
            var message = new Wpf.Ui.Controls.MessageBox();
            message.Owner = this;
            message.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            message.Title = "应用重命名";
            if (applyList.Count() == 0)
            {
                message.Content = "请选择需要应用的文件！";
                message.CloseButtonText = "确认";
            }
            else
            {
                message.Content = $"即将修改{Files.Count}个文件名称，此操作不可逆，请确认！";
                message.PrimaryButtonText = "确认";
                message.CloseButtonText = "取消";
            }
            var messageResult = await message.ShowDialogAsync();
            if (messageResult == Wpf.Ui.Controls.MessageBoxResult.Primary)
            {
                int failed = 0;

                foreach (var file in applyList)
                    file.NewFileName = file.FileName;

                foreach (var rule in Rules)
                    rule.PrewRule(applyList);

                try
                {
                    foreach (var file in applyList)
                    {
                        string newPath = Path.Combine(file.DirPath, file.NewFileName);
                        if (!file.FilePath.Equals(newPath))
                        {
                            if (File.Exists(file.FilePath))
                                File.Move(file.FilePath, newPath);
                            else if (Directory.Exists(file.FilePath))
                                Directory.Move(file.FilePath, newPath);
                        }
                    }
                }
                catch
                {
                    failed++;
                }
                _SnackbarService.Show("应用重命名", $"成功：{applyList.Count() - failed}，失败：{failed}", new SymbolIcon(SymbolRegular.Checkmark48));
            }
        }


        private void ViewChange()
        {
            IsOnlyFolder.Visibility = IsApplyFolder.IsChecked == false ? Visibility.Collapsed : Visibility.Visible;
        }

        private void IsApplyFolder_Click(object sender, RoutedEventArgs e)
        {
            if (this.IsLoaded)
                ViewChange();
        }
    }
}